﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.ExtensibleStorage;
using YArchitech.Controls;

namespace HangerSupport
{
	public class SectionUpdater : IUpdater
	{
		internal SectionUpdater(AddInId addinID)
		{
			this.m_updaterId = new UpdaterId(addinID, new Guid("FBF3F6B2-4C06-42d4-97C1-D1B4EB593EFF"));
			this.m_schemaId = new Guid("4DE4BE80-0857-4785-A7DF-8A8918851CB2");
		}

		internal void Register(Autodesk.Revit.DB.Document doc)
		{
			ElementFilter elementFilter = new ElementCategoryFilter(this.builtInCategory);
			UpdaterRegistry.RegisterUpdater(this, doc);
			UpdaterRegistry.AddTrigger(this.m_updaterId, doc, elementFilter, ChangeType.ConcatenateChangeTypes(Element.GetChangeTypeGeometry(), Element.GetChangeTypeElementAddition()));
		}

		public void Execute(UpdaterData data)
		{
			this.MoveElementOperate(data);
			this.AddElementOperate(data);
		}

		public bool AddElementOperate(UpdaterData data)
		{
			bool result = true;
			try
			{
				List<FamilyInstance> list = null;
				List<FamilyInstance> list2 = null;
				this.GroupAddElementSet(data, ref list, ref list2);
				bool flag = list == null || list.Count < 1 || list2 == null || list2.Count < 1;
				if (flag)
				{
					return result;
				}
				Dictionary<FamilyInstance, List<FamilyInstance>> dictionary = this.SortHangerAndComponents(list, list2);
				AddSeismicComponent addSeismicComponent = new AddSeismicComponent(list.First<FamilyInstance>().Document);
				foreach (KeyValuePair<FamilyInstance, List<FamilyInstance>> keyValuePair in dictionary)
				{
					bool flag2 = keyValuePair.Value == null || keyValuePair.Value.Count < 1;
					if (!flag2)
					{
						foreach (FamilyInstance familyInstance in keyValuePair.Value)
						{
							XYZ point = (familyInstance.Location as LocationPoint).Point;
							addSeismicComponent.BingSeiComLocPoint(familyInstance, point);
						}
						addSeismicComponent.BingSeiComsToHanger(keyValuePair.Key, keyValuePair.Value);
						addSeismicComponent.BingSeiComLocPoint(keyValuePair.Key, (keyValuePair.Key.Location as LocationPoint).Point);
					}
				}
			}
			catch (Exception ex)
			{
				YJKMessageBox.Warning(ex.ToString());
				result = false;
			}
			return result;
		}

		private Dictionary<FamilyInstance, List<FamilyInstance>> SortHangerAndComponents(List<FamilyInstance> listHanger, List<FamilyInstance> listCompenent)
		{
			Dictionary<FamilyInstance, List<FamilyInstance>> dictionary = new Dictionary<FamilyInstance, List<FamilyInstance>>();
			foreach (FamilyInstance familyInstance in listHanger)
			{
				List<FamilyInstance> list = this.GetIntersectComponentToHanger(familyInstance, ref listCompenent);
				bool flag = list == null;
				if (flag)
				{
					list = new List<FamilyInstance>();
				}
				dictionary.Add(familyInstance, list);
			}
			return dictionary;
		}

		private List<FamilyInstance> GetIntersectComponentToHanger(FamilyInstance hanger, ref List<FamilyInstance> listComponent)
		{
			Document document = hanger.Document;
			bool flag = listComponent == null || listComponent.Count < 1;
			List<FamilyInstance> result;
			if (flag)
			{
				result = null;
			}
			else
			{
				FilteredElementCollector filteredElementCollector = new FilteredElementCollector(document);
				filteredElementCollector.OfCategory(BuiltInCategory.OST_MechanicalEquipment);
				ElementIntersectsElementFilter elementIntersectsElementFilter = new ElementIntersectsElementFilter(hanger);
				filteredElementCollector.WherePasses(elementIntersectsElementFilter);
				List<Element> list = filteredElementCollector.ToList<Element>();
				List<FamilyInstance> list2 = new List<FamilyInstance>();
				foreach (Element element in list)
				{
					FamilyInstance component = element as FamilyInstance;
					bool flag2 = component == null || component.Name != "侧向支撑";
					if (!flag2)
					{
						IEnumerable<bool> enumerable = from com in listComponent
						select com.Id == component.Id;
						bool flag3 = enumerable != null || enumerable.Count<bool>() > 0;
						if (flag3)
						{
							list2.Add(component);
						}
					}
				}
				bool flag4 = listComponent.Count > 0 && list2.Count > 0;
				if (flag4)
				{
					foreach (FamilyInstance item in list2)
					{
						listComponent.Remove(item);
					}
				}
				result = list2;
			}
			return result;
		}

		private void GroupAddElementSet(UpdaterData data, ref List<FamilyInstance> listHanger, ref List<FamilyInstance> listComponent)
		{
			listHanger = new List<FamilyInstance>();
			listComponent = new List<FamilyInstance>();
			Document document = data.GetDocument();
			foreach (ElementId elementId in data.GetAddedElementIds())
			{
				FamilyInstance familyInstance = document.GetElement(elementId) as FamilyInstance;
				bool flag = familyInstance == null;
				if (!flag)
				{
					bool flag2 = familyInstance.Name == "侧向支撑";
					if (flag2)
					{
						listComponent.Add(familyInstance);
					}
					else
					{
						bool flag3 = SectionUpdater.filterHangerBySymbolName.Contains(familyInstance.Symbol.Name);
						if (flag3)
						{
							listHanger.Add(familyInstance);
						}
					}
				}
			}
		}

		private bool MoveElementOperate(UpdaterData data)
		{
			bool result = false;
			try
			{
				Document document = data.GetDocument();
				foreach (ElementId elementId in data.GetModifiedElementIds())
				{
					FamilyInstance familyInstance = document.GetElement(elementId) as FamilyInstance;
					bool flag = familyInstance == null;
					if (!flag)
					{
						bool flag2 = familyInstance.Name == "侧向支撑";
						if (flag2)
						{
							XYZ createSeiComLocPoint = this.GetCreateSeiComLocPoint(familyInstance);
							bool flag3 = createSeiComLocPoint == null;
							if (!flag3)
							{
								SectionUpdater.MoveSecComs(document, familyInstance, createSeiComLocPoint);
							}
						}
						else
						{
							bool flag4 = SectionUpdater.filterHangerBySymbolName.Contains(familyInstance.Symbol.Name);
							if (flag4)
							{
								this.MoveHanger(document, familyInstance);
							}
						}
					}
				}
				result = true;
			}
			catch (Exception ex)
			{
				YJKMessageBox.Warning(ex.ToString());
				result = false;
			}
			return result;
		}

		public UpdaterId GetUpdaterId()
		{
			return this.m_updaterId;
		}

		public string GetUpdaterName()
		{
			return "Associative Section Updater";
		}

		public string GetAdditionalInformation()
		{
			return "Automatically moves a section to maintain its position relative to Seismic Component";
		}

		public ChangePriority GetChangePriority()
		{
            return (ChangePriority)(14);
		}

		private static void MoveSecComs(Autodesk.Revit.DB.Document doc, FamilyInstance fi, XYZ ori)
		{
			XYZ point = (fi.Location as LocationPoint).Point;
			XYZ xyz = ori - point;
			bool flag = !xyz.IsZeroLength();
			if (flag)
			{
				ElementTransformUtils.MoveElement(doc, fi.Id, xyz);
			}
		}

		private void MoveHanger(Autodesk.Revit.DB.Document doc, FamilyInstance fi)
		{
			XYZ createSeiComLocPoint = this.GetCreateSeiComLocPoint(fi);
			bool flag = createSeiComLocPoint == null;
			if (!flag)
			{
				XYZ point = (fi.Location as LocationPoint).Point;
				XYZ xyz = point - createSeiComLocPoint;
				foreach (Element element in this.GetLastTimeAddSeiComs(fi, doc))
				{
					FamilyInstance familyInstance = (FamilyInstance)element;
					XYZ createSeiComLocPoint2 = this.GetCreateSeiComLocPoint(familyInstance);
					this.BingSeiComLocPoint(familyInstance, createSeiComLocPoint2 + xyz);
					ElementTransformUtils.MoveElement(doc, familyInstance.Id, xyz);
				}
				this.BingSeiComLocPoint(fi, point);
			}
		}

		private void BingSeiComLocPoint(FamilyInstance fi, XYZ locationPoint)
		{
			Guid guid = new Guid("A705CD05-18AE-4F55-8CE9-0C5C4AC8DC2F");
			bool flag = Schema.Lookup(guid) == null;
			Schema schema;
			if (flag)
			{
				SchemaBuilder schemaBuilder = new SchemaBuilder(guid);
				schemaBuilder.SetReadAccessLevel((AccessLevel)1);
				schemaBuilder.SetWriteAccessLevel((AccessLevel)1);
				schemaBuilder.SetSchemaName("SeismicComponentLocationPoint");
				schemaBuilder.SetDocumentation("Record SeismicComponent locationPoint");
				schemaBuilder.AddSimpleField("locationX", typeof(string));
				schemaBuilder.AddSimpleField("locationY", typeof(string));
				schemaBuilder.AddSimpleField("locationZ", typeof(string));
				schema = schemaBuilder.Finish();
			}
			else
			{
				schema = Schema.Lookup(guid);
			}
			Entity entity = new Entity(schema);
			entity.Set<string>("locationX", locationPoint.X.ToString());
			entity.Set<string>("locationY", locationPoint.Y.ToString());
			entity.Set<string>("locationZ", locationPoint.Z.ToString());
			fi.SetEntity(entity);
		}

		private XYZ GetCreateSeiComLocPoint(FamilyInstance fi)
		{
			Guid guid = new Guid("A705CD05-18AE-4F55-8CE9-0C5C4AC8DC2F");
			bool flag = Schema.Lookup(guid) == null;
			XYZ result;
			if (flag)
			{
				result = null;
			}
			else
			{
				Entity entity = fi.GetEntity(Schema.Lookup(guid));
				bool flag2 = entity.Schema == null;
				if (flag2)
				{
					result = null;
				}
				else
				{
					double num = Convert.ToDouble(entity.Get<string>(Schema.Lookup(guid).GetField("locationX")));
					double num2 = Convert.ToDouble(entity.Get<string>(Schema.Lookup(guid).GetField("locationY")));
					double num3 = Convert.ToDouble(entity.Get<string>(Schema.Lookup(guid).GetField("locationZ")));
					result = new XYZ(num, num2, num3);
				}
			}
			return result;
		}

		public static void GetLinkUpdateHanger()
		{
			for (int i = 1; i < 16; i++)
			{
				SectionUpdater.filterHangerBySymbolName.Add(i + "层吊架");
			}
			SectionUpdater.filterHangerBySymbolName.Add("钢筋吊架");
			SectionUpdater.filterHangerBySymbolName.Add("单管吊架");
		}

		private List<Element> GetLastTimeAddSeiComs(Element hanger, Autodesk.Revit.DB.Document doc)
		{
			List<Element> list = new List<Element>();
			Guid guid = new Guid("BBEC5246-99AA-45B9-A1B1-819109282C3B");
			bool flag = Schema.Lookup(guid) == null;
			List<Element> result;
			if (flag)
			{
				result = list;
			}
			else
			{
				Entity entity = hanger.GetEntity(Schema.Lookup(guid));
				bool flag2 = entity.Schema == null;
				if (flag2)
				{
					result = list;
				}
				else
				{
					string tagIds = entity.Get<string>(Schema.Lookup(guid).GetField("AddSeismicComponents"));
					result = this.GetSeiComs(tagIds, doc);
				}
			}
			return result;
		}

		private List<Element> GetSeiComs(string tagIds, Autodesk.Revit.DB.Document doc)
		{
			List<Element> list = new List<Element>();
			char[] separator = new char[]
			{
				'@'
			};
			string[] array = tagIds.ToString().Split(separator, StringSplitOptions.RemoveEmptyEntries);
			string[] array2 = array;
			int i = 0;
			while (i < array2.Length)
			{
				string s = array2[i];
				int num;
				bool flag = int.TryParse(s, out num);
				if (flag)
				{
					ElementId elementId = new ElementId(num);
					Element element = doc.GetElement(elementId);
					try
					{
						bool flag2 = element != null;
						if (flag2)
						{
							list.Add(element);
						}
					}
					catch (Exception)
					{
					}
				}
				IL_73:
				i++;
				continue;
				goto IL_73;
			}
			return list;
		}

		private static List<string> filterHangerBySymbolName = new List<string>();

		private BuiltInCategory builtInCategory = BuiltInCategory.OST_MechanicalEquipment;

		private Guid m_schemaId;

		private UpdaterId m_updaterId = null;
	}
}
